import { defineComponent, ref, onMounted, watch, onUnmounted } from 'vue'
import SvgIcon from '../SvgIcon/index.vue'
import './index.less'

export default defineComponent({
  props: {
    direction: {
      type: Number,
      default: 1 // 1 右边 -1左边
    },
    step: {
      type: Number,
      default: 3
    },
    value: {
      type: [Number, String]
    },
    title: {
      type: String
    }
  },
  setup(props) {
    const canvasHeight = ref(0)
    const canvasWidth = ref(0)
    const { direction, step } = props
    const radius = 135
    const containerRef = ref<HTMLDivElement | null>(null)
    let canvas: HTMLCanvasElement | null = null
    let ctx: CanvasRenderingContext2D | null = null
    const textRadius = 155
    let prevVal = 0

    const initCavans = () => {
      const parent = containerRef.value
      if (!parent) return
      if (!canvas) {
        canvas = document.createElement('canvas')
        parent.appendChild(canvas)
        ctx = canvas.getContext('2d')
      }
      canvas.height = canvasHeight.value = parseFloat(getComputedStyle(parent).height)
      canvas.width = canvasWidth.value = parseFloat(getComputedStyle(parent).width)
    }

    const drawEcharts = (initVal: number, changeStep: number, target: number) => {
      if (!ctx) return
      const val = initVal + changeStep
      let deflectionAngle = ((val / step) * 3) % 60
      if (deflectionAngle < 0) deflectionAngle += 60
      ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
      ctx.strokeStyle = '#8EA8D5'
      ctx.lineWidth = 2
      for (let i = 0; i < 20; i++) {
        let len = 8
        if (i % 5 == 0) {
          len = 16
        }
        const deg = (direction * (60 + ((i * 3 + deflectionAngle) % 60)) * 2 * Math.PI) / 360
        const x = direction > 0 ? 0 : canvasWidth.value
        const firstPoint = [
          direction * Math.sin(deg * direction) * radius + x,
          -Math.cos(deg) * radius + canvasHeight.value / 2
        ]
        const secondPoint = [
          direction * Math.sin(deg * direction) * (radius + len) + x,
          -Math.cos(deg) * (radius + len) + canvasHeight.value / 2
        ]
        ctx.beginPath()
        ctx.moveTo(firstPoint[0], firstPoint[1])
        ctx.lineTo(secondPoint[0], secondPoint[1])
        ctx.stroke()
      }
      ctx.restore()
      const centerVal = Math.round(val / (5 * step)) * 5 * step
      ctx.translate(direction > 0 ? 0 : canvasWidth.value, canvasHeight.value / 2)
      ctx.textAlign = 'center'
      ctx.font = '16px sans-serif'
      ctx.fillStyle = '#DBF3FE'
      ctx.rotate((direction * 60 * 2 * Math.PI) / 360)
      for (let index = 0; index < 4; index++) {
        ctx.save()
        const tempDeg = (index * 15 + deflectionAngle) % 60
        const text = -Math.round((tempDeg - 30) / (5 * 3)) * 5 * step + centerVal
        const textDeg = (direction * tempDeg * 2 * Math.PI) / 360
        ctx.rotate(textDeg)
        ctx.fillText(text.toString(), 0, -textRadius)
        ctx.restore()
      }
      ctx.restore()
      if (changeStep == 0) {
        return
      } else if (changeStep < 0) {
        if (val <= target) return
      } else {
        if (val >= target) return
      }
      requestAnimationFrame(() => {
        drawEcharts(val, changeStep, target)
      })
    }

    watch(
      () => props.value,
      (val, oldVal) => {
        prevVal = parseFloat(oldVal as string)
        const changeStep = (parseFloat(val as string) - prevVal) / 20
        drawEcharts(prevVal, changeStep, parseFloat(val as string))
      }
    )

    const resizeFun = () => {
      initCavans()
      drawEcharts(
        prevVal || 0,
        ((props.value as number) - prevVal || 0) / 20,
        props.value as number
      )
    }

    onMounted(() => {
      resizeFun()
      window.addEventListener('resize', resizeFun)
    })

    onUnmounted(() => {
      window.removeEventListener('resize', resizeFun)
    })

    const arrowClass = `arrow ${direction > 0 ? 'right-arrow' : 'left-arrow'}`
    const iconClass = direction > 0 ? 'right_error_arrow' : 'left_error_arrow'
    const titleClass = `title ${direction > 0 ? 'right-title' : 'left-title'}`

    return () => (
      <div class="number-dial" ref={containerRef}>
        <SvgIcon iconClass={iconClass} class={arrowClass} />
        <div class={titleClass}>{props.title}</div>
      </div>
    )
  }
})
